﻿using GN.Pay.TradeChannel.DefaultImpl;
using GN.Pay.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GN.Pay.TradeChannel.AliPay.Request
{
    /// <summary>
    /// 支付请求抽象
    /// </summary>
    [Serializable]
    abstract class APayRequest : AServiceRequest
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="order"></param>
        /// <param name="config"></param>
        protected APayRequest(ITradeChannel channel,
            IOrderPayApply order,
            AliPayConfigure config)
        {
            this.Init(channel, order, config);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        protected string DiffDate(IOrderPayApply order)
        {
            var ts = order.ExpireTime - order.StartTime;
            if (ts.TotalMinutes > 0)
            {
                return ((int)ts.TotalMinutes).ToString() + "m";
            }
            return "";
        }

        /// <summary>
        /// 创建请求
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="order"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        private void Init(ITradeChannel channel,
            IOrderPayApply order,
            AliPayConfigure config)
        {
            if (channel == null)
            {
                ExceptionUtils.CheckNotNull(channel, nameof(channel));
            }
            if (order == null)
            {
                channel.ThrowChannelValidationException("请求的 order 为 null");
            }
            if (config == null)
            {
                channel.ThrowChannelValidationException("请求的 config 为 null");
            }
            if (config.ConfigureInfo == null)
            {
                channel.ThrowChannelValidationException("请求的 config 的 ConfigureInfo 为 null");
            }
            Partner = config.ConfigureInfo.AccountId;
            Seller_id = config.ConfigureInfo.AccountId;
            Out_Trade_No = order.OrderNo;
            _Input_Charset = config.Encoding.WebName;
            Payment_Type = "1";
            Sign_Type = "RSA";
            Subject = FixedLengthString(order.Subject, 128);
            Total_Fee = Math.Round(order.OrderMoney, 2);
            Body = FixedLengthString(order.Body, 1000);
            It_b_pay = DiffDate(order);
            Notify_Url = config.PayNotifyUrl;
        }

        /// <summary>
        /// 支付宝合作商户网站唯一订单号。 不可空 最长 64
        /// </summary>
        public string Out_Trade_No { get; set; }

        /// <summary>
        /// 商品名称 商品的标题/交易标题/订单标题/订单关键字等。 该参数最长为128个汉字。
        /// </summary>
        public string Subject { get; set; }

        /// <summary>
        /// 支付类型,目前只支持取值为1（商品购买）。
        /// </summary>
        public string Payment_Type { get; set; }

        /// <summary>
        /// 交易金额 该笔订单的资金总额，单位为RMB-Yuan。取值范围为[0.01，100000000.00]，精确到小数点后两位。
        /// </summary>
        public decimal Total_Fee { get; set; }

        /// <summary>
        /// 商品描述 对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。Max 1000
        /// </summary>
        public string Body { get; set; }

        /// <summary>
        /// 服务器异步通知页面路径
        /// </summary>
        public string Notify_Url { get; set; }

        /// <summary>
        /// 超时时间 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭。
        ///  取值范围：1m～15d。
        ///  m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。
        ///  该参数数值不接受小数点，如1.5h，可转换为90m。
        /// </summary>
        public string It_b_pay { get; set; }

        /// <summary>
        /// 卖家支付宝用户号
        /// </summary>
        public string Seller_id { get; set; }
     
        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="config">配置</param>
        /// <returns></returns>
        public virtual ITradePayApplyResult Build(ITradeChannel channel,
            AliPayConfigure config)
        {
            var param = this.BuildSignUrlLinkParam(channel, config, "Sign", "Sign_Type");
            return new TradePayApplyResult("", config.GateWayUrl, param, TradePayApplyResultCallType.Web_Get);
        }
    }
}
